<!DOCTYPE html>
<html>
<!--
Creates 4 WebGL canvases with the cross-product of anti-aliasing and
premultiplied alpha. Uses drawingBufferStorage to ensure these canvases are
floating-point. Draws and reads back the color #800080, with slight
perturbations to ensure that greater than 8-bit precision is preserved in
the round-trip.
-->
<head>
<style type="text/css">
  .nomargin {
    margin: 0;
  }
</style>
<script>
function sendResult(status) {
  if (window.domAutomationController) {
    window.domAutomationController.send(status);
  } else {
    console.log(status);
  }
}

var g_swapsBeforeAck = 15;
function waitForFinish() {
  if (g_swapsBeforeAck == 0) {
    sendResult("SUCCESS");
  } else {
    g_swapsBeforeAck--;
    window.requestAnimationFrame(waitForFinish);
  }
}

function drawQuad(gl, color) {
  let ext = gl.getExtension('EXT_color_buffer_half_float');
  if (!ext) {
    send("FAILURE", "EXT_color_buffer_half_float not supported");
    return;
  }

  gl.drawingBufferStorage(gl.RGBA16F, gl.drawingBufferWidth, gl.drawingBufferHeight);

  // Create the program to draw a point sprite.
  let program = null;
  {
    let compileShader = function(gl, vertCode, fragCode) {
      let vertShader = gl.createShader(gl.VERTEX_SHADER);
      gl.shaderSource(vertShader, vertCode);
      gl.compileShader(vertShader);
      if (!gl.getShaderParameter(vertShader, gl.COMPILE_STATUS))
        throw new Error(gl.getShaderInfoLog(vertShader));

      let fragShader = gl.createShader(gl.FRAGMENT_SHADER);
      gl.shaderSource(fragShader, fragCode);
      gl.compileShader(fragShader);
      if (!gl.getShaderParameter(fragShader, gl.COMPILE_STATUS))
        throw new Error(gl.getShaderInfoLog(fragShader));

      let shaderProgram = gl.createProgram();
      gl.attachShader(shaderProgram, vertShader);
      gl.attachShader(shaderProgram, fragShader);
      gl.linkProgram(shaderProgram);
      if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS))
        throw new Error(gl.getProgramInfoLog(program));

      return shaderProgram;
    }
    let vs = `attribute vec2 position;
              void main() {
                gl_Position = vec4(position, 0.0, 1.0);
              }`;
    let fs = `precision mediump float;
              uniform vec4 color;
              void main() {
                gl_FragColor = color;
              }`;
    program = compileShader(gl, vs, fs);
  }
  gl.useProgram(program);

  // Draw using that program.
  {
    let vertices = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertices);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1, 1,-1, 1,1, -1,1]), gl.STATIC_DRAW);

    let indices = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indices);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0,1,2, 0,2,3]), gl.STATIC_DRAW);

    let positionLocation = gl.getAttribLocation(program, 'position');
    gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(positionLocation);

    gl.uniform4fv(gl.getUniformLocation(program, 'color'), color);
    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
  }

  // Ensure that we can read the values back as FLOAT, and that the output
  // matches the input with higher precision than we can achieve with 8 bits.
  let pixels = new Float32Array(4);
  gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, pixels);
  for (let c = 0; c < 4; ++c) {
    const epsilon = (1/255) / 8;
    if (Math.abs(pixels[c] - color[c]) > epsilon)
      throw new Error('Error reading back pixels as floats');
  }
}

async function main() {
  let color = new Float32Array(4);

  color[0] = 1.0;
  color[1] = 0.0;
  color[2] = (128 + 1/4) / 255;
  color[3] = 1.0;
  {
    let element = document.getElementById('canvas-noaa-premul');
    let gl = element.getContext('webgl2', {premultipliedAlpha: true, antialias:false});
    drawQuad(gl, color);
  }
  {
    let element = document.getElementById('canvas-aa-premul');
    let gl = element.getContext('webgl2', {premultipliedAlpha: true, antialias:true});
    drawQuad(gl, color);
  }

  {
    let element = document.getElementById('canvas-noaa-unpremul');
    let gl = element.getContext('webgl2', {premultipliedAlpha: false, antialias:false});
    drawQuad(gl, color);
  }
  {
    let element = document.getElementById('canvas-aa-unpremul');
    let gl = element.getContext('webgl2', {premultipliedAlpha: false, antialias:true});
    drawQuad(gl, color);
  }

  waitForFinish();
}
</script>
</head>
<body onload='main()'>
  <p>
  <canvas id='canvas-aa-premul' width='32' height='32'></canvas>
  <canvas id='canvas-aa-unpremul' width='32' height='32'></canvas>
  <canvas id='canvas-noaa-premul' width='32' height='32'></canvas>
  <canvas id='canvas-noaa-unpremul' width='32' height='32'></canvas>
  </p>
</body>
</html>
